﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Fantom.Expression
{
    /// <summary>
    /// 函数清单。
    /// </summary>
    public class FunctionCatalog: Dictionary<string, FunctionNode>
    {
        public delegate double ZeroParaCustomFunctionHandler();
        public delegate double OneParaCustomFunctionHandler(double num1);
        public delegate double TwoParaCustomFunctionHandler(double num1, double num2);
        public delegate double ThreeParaCustomFunctionHandler(double num1, double num2, double num3);
        public delegate double FourParaCustomFunctionHandler(double num1, double num2, double num3, double num4);
        public delegate double FiveParaCustomFunctionHandler(double num1, double num2, double num3, double num4, double num5);
        public delegate double SixParaCustomFunctionHandler(double num1, double num2, double num3, double num4, double num5, double num6);

        /// <summary>
        /// 函数清单目录，您可以在此处注册自定义函数。
        /// </summary>
        public static FunctionCatalog DefaultFunctions => _defaultDic;
        private static FunctionCatalog _defaultDic = new FunctionCatalog();

        private static Random _rand = new Random();


        public FunctionCatalog()
        {

        }

        static FunctionCatalog()
        {
            DefaultDicAddFunc("rand", (num1) => _rand.NextDouble() * num1);

            DefaultDicAddFunc("sin", (num) => Math.Sin(num));
            DefaultDicAddFunc("cos", (num) => Math.Cos(num));
            DefaultDicAddFunc("tan", (num) => Math.Tan(num));

            DefaultDicAddFunc("abs", (num) => Math.Abs(num));

            DefaultDicAddFunc("floor", (num) => Math.Floor(num));
            DefaultDicAddFunc("ceil", (num) => Math.Ceiling(num));

            DefaultDicAddFunc("max", (num1, num2) => Math.Max(num1, num2));
            DefaultDicAddFunc("min", (num1, num2) => Math.Min(num1, num2));

        }

        #region DefaultDicAddFunc
        private static void AddFunc(string name, int para = 2, FunctionNode.FuncHandler func = null)
        {
            _defaultDic.Add(name, new FunctionNode() { Name = name, ParameterCount = para, Func = func });
        }

        static void DefaultDicAddFunc(string name, ZeroParaCustomFunctionHandler handler)
        {
            AddFunc(name, 0, (num1, num2, num3, num4, num5, num6) => handler());
        }

        static void DefaultDicAddFunc(string name, OneParaCustomFunctionHandler handler)
        {
            AddFunc(name, 1, (num1, num2, num3, num4, num5, num6) => handler(num1));
        }
        static void DefaultDicAddFunc(string name, TwoParaCustomFunctionHandler handler)
        {
            AddFunc(name, 2, (num1, num2, num3, num4, num5, num6) => handler(num1, num2));
        }
        static void DefaultDicAddFunc(string name, ThreeParaCustomFunctionHandler handler)
        {
            AddFunc(name, 3, (num1, num2, num3, num4, num5, num6) => handler(num1, num2, num3));
        }
        static void DefaultDicAddFunc(string name, FourParaCustomFunctionHandler handler)
        {
            AddFunc(name, 4, (num1, num2, num3, num4, num5, num6) => handler(num1, num2, num3, num4));
        }
        static void DefaultDicAddFunc(string name, FiveParaCustomFunctionHandler handler)
        {
            AddFunc(name, 5, (num1, num2, num3, num4, num5, num6) => handler(num1, num2, num3, num4, num5));
        }

        static void DefaultDicAddFunc(string name, SixParaCustomFunctionHandler handler)
        {
            AddFunc(name, 6, (num1, num2, num3, num4, num5, num6) => handler(num1, num2, num3, num4, num5, num6));
        }

        #endregion

    }
}
